﻿using System;
using System.Collections.Generic;
using System.Linq;
using Gumini.JulaDB.DataTypes;
using Gumini.JulaDB.Expressions.Operators;

namespace Gumini.JulaDB.Expressions
{
    /// <summary>
    /// A node in the expression tree that has two child nodes and a binary operator.
    /// </summary>
    internal class BinaryExpression : Expression
    {
        public BinaryExpression(string op, Expression left, Expression right)
            : base(left, right)
        {
            this.Operator = OperatorFactory.GetBinaryOperator(op);
        }

        public BinaryOperator Operator { get; private set; }

        public Expression Left
        {
            get { return base._children[0]; }
        }

        public Expression Right
        {
            get { return base._children[1]; }
        }

        public override TypedValue Evaluate(List<Context<TypedValue>> context)
        {
            var leftResult = this.Left.Evaluate(context);
            var rightResult = this.Right.Evaluate(context);

            return this.Operator.Evaluate(leftResult, rightResult);
        }

        public override DataType InferType(Context<DataType> context)
        {
            Left.InferType(context);
            Right.InferType(context);

            return this.Operator.GetReturnType();
        }

        public override bool Equals(Expression other)
        {
            var b = other as BinaryExpression;
            if (b == null)
                return false;
            return
                this.Operator == b.Operator &&
                this.Left.Equals(b.Left) &&
                this.Right.Equals(b.Right);
        }

        public override string ToString()
        {
            return String.Format("({0} {1} {2})", this.Left, this.Operator.Names.First(), this.Right);
        }
    }
}
